/********************************************************************************
  * @Copyright: Metanergy Technology R&D Co., Ltd
  * @Filename: myg0025_dma.c
  * @brief: DMA init and functions configure
  * @Author: AE Team
  * @Version: V1.0.0/2023-04-09
  *******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "myg0025_dma.h"

/** @addtogroup myg0025_StdPeriph_Driver
  * @{
  */

/** @defgroup DMA DMA
  * @brief DMA driver modules
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* DMA Channel config registers Masks */
#define CCR_CLEAR_MASK   ((uint32_t)0xFFFF800F)
#define FLAG_Mask        ((uint32_t)0x10000000)


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup DMA_Private_Functions DMA_Private_Functions
  * @{
  */

/** @defgroup DMA_Group1 Initialization and Configuration functions
 *  @brief   Initialization and Configuration functions
 *
@verbatim
 ===============================================================================
            ##### Initialization and Configuration functions #####
 ===============================================================================
    [..] This subsection provides functions allowing to initialize the DMA channel
         source and destination addresses, incrementation and data sizes, transfer
         direction, buffer size, circular/normal mode selection, memory-to-memory
         mode selection and channel priority value.
    [..] The DMA_Init() function follows the DMA configuration procedures as described
         in reference manual .
@endverbatim
  * @{
  */

/**
  * @brief  Deinitializes the DMA Channelx registers to their default reset
  *         values.
  * @note   None
  * @param  DMA_Channelx: where x can be 1 to 5 for DMA to select the DMA Channel.
  *
  * @retval None
  */
void DMA_DeInit(DMA_TypeDef *DMA_Channelx)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));

    /* Disable the selected DMA Channelx */
    DMA_Channelx->CCR &= (uint16_t)(~DMA_CCR_EN);

    /* Reset DMA Channelx control register */
    DMA_Channelx->CCR  = 0;

    /* Reset DMA Channelx remaining bytes register */
    DMA_Channelx->CNDTR = 0;

    /* Reset DMA Channelx peripheral address register */
    DMA_Channelx->CPAR  = 0;

    /* Reset DMA Channelx memory address register */
    DMA_Channelx->CMAR = 0;
    /* Reset interrupt pending bits for DMA Channelx */
    DMA_Channelx->IFCR = ((uint32_t)(DMA_IFCR_CTEIF | DMA_IFCR_CHTIF | DMA_IFCR_CTCIF | DMA_IFCR_CGIF));

}

/**
  * @brief  Initializes the DMA Channelx according to the specified parameters
  *         in the DMA_InitStruct.
  * @note   None
  * @param  DMA_Channelx: where x can be 1 to 5 for DMA to select the DMA Channel.
  *
  * @param  DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains
  *         the configuration information for the specified DMA Channel.
  * @retval None
  */
void DMA_Init(DMA_TypeDef *DMA_Channelx, DMA_InitTypeDef *DMA_InitStruct)
{
    uint32_t tmpreg = 0;

    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));
    assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR));
    assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize));
    assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc));
    assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc));
    assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize));
    assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize));
    assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode));
    assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority));
    assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M));
    assert_param(IS_DMA_REQ_SRC(DMA_InitStruct->DMA_Request_Source));//------------------------
    /*--------------------------- DMA Channelx CCR Configuration ----------------*/
    /* Get the DMA_Channelx CCR value */
    tmpreg = DMA_Channelx->CCR;

    /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
    tmpreg &= CCR_CLEAR_MASK;

    /* Configure DMA Channelx: data transfer, data size, priority level and mode */
    /* Set DIR bit according to DMA_DIR value */
    /* Set CIRC bit according to DMA_Mode value */
    /* Set PINC bit according to DMA_PeripheralInc value */
    /* Set MINC bit according to DMA_MemoryInc value */
    /* Set PSIZE bits according to DMA_PeripheralDataSize value */
    /* Set MSIZE bits according to DMA_MemoryDataSize value */
    /* Set PL bits according to DMA_Priority value */
    /* Set the MEM2MEM bit according to DMA_M2M value */
    tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode |
              DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc |
              DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize |
              DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M;

    /* Write to DMA Channelx CCR */
    DMA_Channelx->CCR = tmpreg;
    /* Write to DMA Channelx CNDTR */
    DMA_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;
    /* Write to DMA Channelx CPAR */
    DMA_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr;
    /* Write to DMA Channelx CMAR */
    DMA_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr;

    DMA_RequesrSocreConfig(DMA_Channelx, DMA_InitStruct->DMA_Request_Source);
}

/**
  * @brief  Fills each DMA_InitStruct member with its default value.
  * @note   None
  * @param  DMA_InitStruct: pointer to a DMA_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */

void DMA_StructInit(DMA_InitTypeDef *DMA_InitStruct)
{
    /*-------------- Reset DMA init structure parameters values ------------------*/
    /* Initialize the DMA_PeripheralBaseAddr member */
    DMA_InitStruct->DMA_PeripheralBaseAddr = 0;
    /* Initialize the DMA_MemoryBaseAddr member */
    DMA_InitStruct->DMA_MemoryBaseAddr = 0;
    /* Initialize the DMA_DIR member */
    DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC;
    /* Initialize the DMA_BufferSize member */
    DMA_InitStruct->DMA_BufferSize = 0;
    /* Initialize the DMA_PeripheralInc member */
    DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    /* Initialize the DMA_MemoryInc member */
    DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable;
    /* Initialize the DMA_PeripheralDataSize member */
    DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    /* Initialize the DMA_MemoryDataSize member */
    DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    /* Initialize the DMA_Mode member */
    DMA_InitStruct->DMA_Mode = DMA_Mode_Normal;
    /* Initialize the DMA_Priority member */
    DMA_InitStruct->DMA_Priority = DMA_Priority_Low;
    /* Initialize the DMA_M2M member */
    DMA_InitStruct->DMA_M2M = DMA_M2M_Disable;
}

/**
  * @brief  Enables or disables the specified DMA Channelx.
  * @note   None
  * @param  DMA_Channelx: where x can be 1 to 5 for DMA to select the DMA Channel.
  *
  * @param  NewState: new state of the DMA Channelx.
  *         This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void DMA_Cmd(DMA_TypeDef *DMA_Channelx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected DMA Channelx */
        DMA_Channelx->CCR |= DMA_CCR_EN;

    }
    else
    {
        /* Disable the selected DMA Channelx */
        DMA_Channelx->CCR &= (uint16_t)(~DMA_CCR_EN);
    }
}

/**
  * @brief  Configure the DMA channels request number.
  * @note   None
  * @param  DMA_Channelx: where x can be 1~5 to select the DMA peripheral channel.
  * @param  DMA_CHx_Request:
    *       This parameter can be one of the following values:
    *          @arg DMA_REQ_ADC_QUE0    : DMA ADC_QUE0 request.
    *          @arg DMA_REQ_ADC_QUE1    : DMA ADC_QUE1 request.
    *          @arg DMA_REQ_ADC_QUE2    : DMA ADC_QUE2 request.
    *          @arg DMA_REQ_ADC_QUE3    : DMA ADC_QUE3 request.
    *          @arg DMA_REQ_ADC_COM     : DMA ADC_COM request.
    *          @arg DMA_REQ_SPI1_RX     : DMA ADC_QUE0 request.
    *          @arg DMA_REQ_SPI1_TX     : DMA SPI1_RX request.
    *          @arg DMA_REQ_UART1_RX    : DMA UART1_RX request.
    *              @arg DMA_REQ_UART1_TX    : DMA UART1_TX request.
    *          @arg DMA_REQ_UART2_RX    : DMA UART2_RX request.
    *          @arg DMA_REQ_UART2_TX    : DMA UART2_TX request.
    *          @arg DMA_REQ_I2C1_TX     : DMA I2C1_TX request.
    *          @arg DMA_REQ_I2C1_RX     : DMA I2C1_RX  request.
    *          @arg DMA_REQ_TIM1_CH1    : DMA TIM1_CH1 request.
    *          @arg DMA_REQ_TIM1_CH2    : DMA TIM1_CH2 request.
    *          @arg DMA_REQ_TIM1_CH3    : DMA TIM1_CH3 request.
    *          @arg DMA_REQ_TIM1_CH4    : DMA TIM1_CH4 request.
    *          @arg DMA_REQ_TIM1_UP     : DMA TIM1_UP request.
    *          @arg DMA_REQ_TIM1_TRIG   : DMA TIM1_TRIG  request.
    *          @arg DMA_REQ_TIM1_COM    : DMA TIM1_COM request.
    *          @arg DMA_REQ_TIM2_CH1    : DMA TIM2_CH1 request.
    *          @arg DMA_REQ_TIM2_CH2    : DMA TIM2_CH2 request.
    *          @arg DMA_REQ_TIM2_CH3    : DMA ADC_QUE3 request.
    *          @arg DMA_REQ_TIM2_CH4    : DMA TIM2_CH4 request.
    *          @arg DMA_REQ_TIM2_UP     : DMA TIM2_UP request.
    *          @arg DMA_REQ_TIM2_TRIG   : DMA TIM2_TRIG request.
    *          @arg DMA_REQ_TIM3_CH1    : DMA TIM3_CH1 request.
    *              @arg DMA_REQ_TIM3_CH2    : DMA TIM3_CH2 request.
    *          @arg DMA_REQ_TIM3_CH3    : DMA TIM3_CH3 request.
    *          @arg DMA_REQ_TIM3_CH4    : DMA TIM3_CH4 request.
    *          @arg DMA_REQ_TIM3_UP     : DMA TIM3_UP request.
    *          @arg DMA_REQ_TIM3_TRIG   : DMA TIM3_TRIG  request.
    * @retval None
  */
void DMA_RequesrSocreConfig(DMA_TypeDef *DMA_Channelx, uint32_t DMA_CHx_Request)
{

    assert_param(IS_DMA_REQ_SRC(DMA_CHx_Request));

    DMA_Channelx->CSELR &= ~((uint32_t)0x0000001F);
    DMA_Channelx->CSELR |= (uint32_t)(DMA_CHx_Request);
}

/**
  * @}
  */

/** @defgroup DMA_Group2 Data Counter functions
 *  @brief   Data Counter functions
 *

@verbatim
 ===============================================================================
                      ##### Data Counter functions #####
 ===============================================================================
    [..] This subsection provides function allowing to configure and read the buffer
         size (number of data to be transferred).The DMA data counter can be written
         only when the DMA channel is disabled (ie. after transfer complete event).
    [..] The following function can be used to write the Channel data counter value:
         (+) void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx, uint16_t
             DataNumber).
    -@- It is advised to use this function rather than DMA_Init() in situations
        where only the Data buffer needs to be reloaded.
    [..] The DMA data counter can be read to indicate the number of remaining transfers
         for the relative DMA channel. This counter is decremented at the end of each
         data transfer and when the transfer is complete:
         (+) If Normal mode is selected: the counter is set to 0.
         (+) If Circular mode is selected: the counter is reloaded with the initial
         value(configured before enabling the DMA channel).
    [..] The following function can be used to read the Channel data counter value:
         (+) uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMA_Channelx).

@endverbatim
  * @{
  */

/**
  * @brief  Sets the number of data units in the current DMA Channelx transfer.
  * @note   None
  * @param  DMA_Channelx: where x can be 1 to 5
  *         for DMA to select the DMA Channel .
  * @param  DataNumber: The number of data units in the current DMA Channelx
  *         transfer.
  * @note   This function can only be used when the DMA_Channelx is disabled.
  * @retval None.
  */
void DMA_SetCurrDataCounter(DMA_TypeDef *DMA_Channelx, uint16_t DataNumber)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));
    /* Write to DMA Channelx CNDTR */
    DMA_Channelx->CNDTR = DataNumber;
}

/**
  * @brief  Returns the number of remaining data units in the current
  *         DMA Channelx transfer.
  * @note   None
  * @param  DMA_Channelx: where x can be 1 to 5
  *         for DMA to select the DMA Channel.
  * @retval The number of remaining data units in the current DMA Channelx
  *         transfer.
  */
uint16_t DMA_GetCurrDataCounter(DMA_TypeDef *DMA_Channelx)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));
    /* Return the number of remaining data units for DMA Channelx */
    return ((uint16_t)(DMA_Channelx->CNDTR));
}

/**
  * @}
  */

/** @defgroup DMA_Group3 Interrupts and flags management functions
 *  @brief   Interrupts and flags management functions
 *
@verbatim
 ===============================================================================
          ##### Interrupts and flags management functions #####
 ===============================================================================
    [..] This subsection provides functions allowing to configure the DMA Interrupts
         sources and check or clear the flags or pending bits status.
         The user should identify which mode will be used in his application to manage
         the DMA controller events: Polling mode or Interrupt mode.
  *** Polling Mode ***
  ====================
    [..] Each DMA channel can be managed through 4 event Flags:( x : DMA channel number ).
         (#) DMA_FLAG_TCx : to indicate that a Transfer Complete event occurred.
         (#) DMA_FLAG_HTx : to indicate that a Half-Transfer Complete event occurred.
         (#) DMA_FLAG_TEx : to indicate that a Transfer Error occurred.
         (#) DMA_FLAG_GLx : to indicate that at least one of the events described
             above occurred.
    -@- Clearing DMA_FLAG_GLx results in clearing all other pending flags of the
        same channel (DMA_FLAG_TCx, DMA_FLAG_HTx and DMA_FLAG_TEx).
    [..]In this Mode it is advised to use the following functions:
        (+) FlagStatus DMA_GetFlagStatus(uint32_t DMA_FLAG);
        (+) void DMA_ClearFlag(uint32_t DMA_FLAG);

  *** Interrupt Mode ***
  ======================
    [..] Each DMA channel can be managed through 4 Interrupts:
    (+) Interrupt Source
       (##) DMA_IT_TC: specifies the interrupt source for the Transfer Complete
            event.
       (##) DMA_IT_HT : specifies the interrupt source for the Half-transfer Complete
            event.
       (##) DMA_IT_TE : specifies the interrupt source for the transfer errors event.
       (##) DMA_IT_GL : to indicate that at least one of the interrupts described
            above occurred.
    -@@- Clearing DMA_IT_GL interrupt results in clearing all other interrupts of
        the same channel (DMA_IT_TCx, DMA_IT_HT and DMA_IT_TE).
    [..]In this Mode it is advised to use the following functions:
        (+) void DMA_ITConfig(DMA_Channel_TypeDef* DMA_Channelx, uint32_t DMA_IT,
            FunctionalState NewState);
        (+) ITStatus DMA_GetITStatus(uint32_t DMA_IT);
        (+) void DMA_ClearITPendingBit(uint32_t DMA_IT);

@endverbatim
  * @{
  */

/**
  * @brief   Enables or disables the specified DMA Channelx interrupts.
  * @note    None
  * @param   DMA_Channelx: where x can be 1 to 5
  *          for DMA to select the DMA Channel .
  * @param   DMA_IT: specifies the DMA interrupts sources to be enabled
  *          or disabled.
  *          This parameter can be any combination of the following values:
  *           @arg DMA_IT_TC: Transfer complete interrupt mask
  *           @arg DMA_IT_HT: Half transfer interrupt mask
  *           @arg DMA_IT_TE: Transfer error interrupt mask
  * @param   NewState: new state of the specified DMA interrupts.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval  None
  */
void DMA_ITConfig(DMA_TypeDef *DMA_Channelx, uint32_t DMA_IT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_DMA_ALL_PERIPH(DMA_Channelx));
    assert_param(IS_DMA_CONFIG_IT(DMA_IT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected DMA interrupts */
        DMA_Channelx->CCR |= DMA_IT;
    }
    else
    {
        /* Disable the selected DMA interrupts */
        DMA_Channelx->CCR &= ~DMA_IT;
    }
}

/**
  * @brief  Checks whether the specified DMA Channelx flag is set or not.
  * @note   The Global flag (DMA_FLAG_GLx) is set whenever any of the other flags
  *         relative to the same channel is set (Transfer Complete, Half-transfer
  *         Complete or Transfer Error flags: DMA_FLAG_TCx, DMA_FLAG_HTx or
  *         DMA_FLAG_TEx).
  * @param  DMA_FLAG: specifies the flag to check.
  *         This parameter can be one of the following values:
  *          @arg DMA_FLAG_GL1: DMA Channel1 global flag.
  *          @arg DMA_FLAG_TC1: DMA Channel1 transfer complete flag.
  *          @arg DMA_FLAG_HT1: DMA Channel1 half transfer flag.
  *          @arg DMA_FLAG_TE1: DMA Channel1 transfer error flag.
  *          @arg DMA_FLAG_GL2: DMA Channel2 global flag.
  *          @arg DMA_FLAG_TC2: DMA Channel2 transfer complete flag.
  *          @arg DMA_FLAG_HT2: DMA Channel2 half transfer flag.
  *          @arg DMA_FLAG_TE2: DMA Channel2 transfer error flag.
  *          @arg DMA_FLAG_GL3: DMA Channel3 global flag.
  *          @arg DMA_FLAG_TC3: DMA Channel3 transfer complete flag.
  *          @arg DMA_FLAG_HT3: DMA Channel3 half transfer flag.
  *          @arg DMA_FLAG_TE3: DMA Channel3 transfer error flag.
  *          @arg DMA_FLAG_GL4: DMA Channel4 global flag.
  *          @arg DMA_FLAG_TC4: DMA Channel4 transfer complete flag.
  *          @arg DMA_FLAG_HT4: DMA Channel4 half transfer flag.
  *          @arg DMA_FLAG_TE4: DMA Channel4 transfer error flag.
  *          @arg DMA_FLAG_GL5: DMA Channel5 global flag.
  *          @arg DMA_FLAG_TC5: DMA Channel5 transfer complete flag.
  *          @arg DMA_FLAG_HT5: DMA Channel5 half transfer flag.
  *          @arg DMA_FLAG_TE5: DMA Channel5 transfer error flag.
  * @retval The new state of DMA_FLAG (SET or RESET).
  */
FlagStatus DMA_GetFlagStatus(uint32_t DMA_FLAG)
{
    FlagStatus bitstatus = RESET;
    DMA_TypeDef *dma_address = NULL;

    uint32_t tmpreg = 0;
    uint8_t dma_channel_interrupt = 0;
    /* Check the parameters */
    assert_param(IS_DMA_GET_FLAG(DMA_FLAG));

    /*Get the channel interrupt number*/
    dma_channel_interrupt = (uint8_t)((DMA_FLAG >> 24) & 0x0F);

    /* Calculate the used DMA */
    /* Get DMA ISR register value */
    dma_address = (DMA_TypeDef *)(DMA_Channel1_BASE + dma_channel_interrupt * 0x00000020);
    tmpreg = (dma_address->ISR & 0x0000000F) ;

    /* Check the status of the specified DMA flag */
    if ((tmpreg & DMA_FLAG) != (uint32_t)RESET)
    {
        /* DMA_FLAG is set */
        bitstatus = SET;
    }
    else
    {
        /* DMA_FLAG is reset */
        bitstatus = RESET;
    }

    /* Return the DMA_FLAG status */
    return  bitstatus;
}

/**
  * @brief  Clears the DMA Channelx's pending flags.
  * @note   Clearing the Global flag (DMA_FLAG_GLx) results in clearing all other flags
  *         relative to the same channel (Transfer Complete, Half-transfer Complete and
  *         Transfer Error flags: DMA_FLAG_TCx, DMA_FLAG_HTx and DMA_FLAG_TEx).
  * @param  DMA_FLAG: specifies the flag to clear.
  *         This parameter can be any combination (for the same DMA) of the following values:
  *          @arg DMA_FLAG_GL1: DMA Channel1 global flag.
  *          @arg DMA_FLAG_TC1: DMA Channel1 transfer complete flag.
  *          @arg DMA_FLAG_HT1: DMA Channel1 half transfer flag.
  *          @arg DMA_FLAG_TE1: DMA Channel1 transfer error flag.
  *          @arg DMA_FLAG_GL2: DMA Channel2 global flag.
  *          @arg DMA_FLAG_TC2: DMA Channel2 transfer complete flag.
  *          @arg DMA_FLAG_HT2: DMA Channel2 half transfer flag.
  *          @arg DMA_FLAG_TE2: DMA Channel2 transfer error flag.
  *          @arg DMA_FLAG_GL3: DMA Channel3 global flag.
  *          @arg DMA_FLAG_TC3: DMA Channel3 transfer complete flag.
  *          @arg DMA_FLAG_HT3: DMA Channel3 half transfer flag.
  *          @arg DMA_FLAG_TE3: DMA Channel3 transfer error flag.
  *          @arg DMA_FLAG_GL4: DMA Channel4 global flag.
  *          @arg DMA_FLAG_TC4: DMA Channel4 transfer complete flag.
  *          @arg DMA_FLAG_HT4: DMA Channel4 half transfer flag.
  *          @arg DMA_FLAG_TE4: DMA Channel4 transfer error flag.
  *          @arg DMA_FLAG_GL5: DMA Channel5 global flag.
  *          @arg DMA_FLAG_TC5: DMA Channel5 transfer complete flag.
  *          @arg DMA_FLAG_HT5: DMA Channel5 half transfer flag.
  *          @arg DMA_FLAG_TE5: DMA Channel5 transfer error flag.
  * @retval None
  */
void DMA_ClearFlag(uint32_t DMA_FLAG)
{
    DMA_TypeDef *dma_address = NULL;

    uint8_t dma_channel_interrupt = 0;

    /* Check the parameters */
    assert_param(IS_DMA_CLEAR_FLAG(DMA_FLAG));

    /*Get the channel interrupt number*/
    dma_channel_interrupt = (uint8_t)((DMA_FLAG >> 24) & 0x0F);

    /* Calculate the used DMA */
    /* Clear the selected DMA flags */
    dma_address = (DMA_TypeDef *)(DMA_Channel1_BASE + dma_channel_interrupt * 0x00000020);
    dma_address->IFCR |= (DMA_FLAG & 0x0000000F);


}

/**
  * @brief  Checks whether the specified DMA Channelx interrupt has occurred or not.
  * @note   The Global interrupt (DMA_FLAG_GLx) is set whenever any of the other
  *         interrupts relative to the same channel is set (Transfer Complete,
  *         Half-transfer Complete or Transfer Error interrupts: DMA_IT_TCx,
  *         DMA_IT_HTx or DMA_IT_TEx).
  * @param  DMA_IT: specifies the DMA interrupt source to check.
  *         This parameter can be one of the following values:
  *          @arg DMA_IT_GL1: DMA Channel1 global interrupt.
  *          @arg DMA_IT_TC1: DMA Channel1 transfer complete interrupt.
  *          @arg DMA_IT_HT1: DMA Channel1 half transfer interrupt.
  *          @arg DMA_IT_TE1: DMA Channel1 transfer error interrupt.
  *          @arg DMA_IT_GL2: DMA Channel2 global interrupt.
  *          @arg DMA_IT_TC2: DMA Channel2 transfer complete interrupt.
  *          @arg DMA_IT_HT2: DMA Channel2 half transfer interrupt.
  *          @arg DMA_IT_TE2: DMA Channel2 transfer error interrupt.
  *          @arg DMA_IT_GL3: DMA Channel3 global interrupt.
  *          @arg DMA_IT_TC3: DMA Channel3 transfer complete interrupt.
  *          @arg DMA_IT_HT3: DMA Channel3 half transfer interrupt.
  *          @arg DMA_IT_TE3: DMA Channel3 transfer error interrupt.
  *          @arg DMA_IT_GL4: DMA Channel4 global interrupt.
  *          @arg DMA_IT_TC4: DMA Channel4 transfer complete interrupt.
  *          @arg DMA_IT_HT4: DMA Channel4 half transfer interrupt.
  *          @arg DMA_IT_TE4: DMA Channel4 transfer error interrupt.
  *          @arg DMA_IT_GL5: DMA Channel5 global interrupt.
  *          @arg DMA_IT_TC5: DMA Channel5 transfer complete interrupt.
  *          @arg DMA_IT_HT5: DMA Channel5 half transfer interrupt.
  *          @arg DMA_IT_TE5: DMA Channel5 transfer error interrupt.
  * @retval The new state of DMA_IT (SET or RESET).
  */
ITStatus DMA_GetITStatus(uint32_t DMA_IT)
{
    ITStatus bitstatus = RESET;
    DMA_TypeDef *dma_address = NULL;

    uint32_t tmpreg = 0;
    uint8_t dma_channel_interrupt = 0;

    /* Check the parameters */
    assert_param(IS_DMA_GET_IT(DMA_IT));

    /*Get the channel interrupt number*/
    dma_channel_interrupt = (uint8_t)((DMA_IT >> 24) & 0x0F);

    /* Calculate the used DMA */
    /* Get DMA ISR register value */
    dma_address = (DMA_TypeDef *)(DMA_Channel1_BASE + dma_channel_interrupt * 0x00000020);
    tmpreg = (dma_address->ISR & 0x0000000F) ;


    /* Check the status of the specified DMA interrupt */
    if ((tmpreg & DMA_IT) != (uint32_t)RESET)
    {
        /* DMA_IT is set */
        bitstatus = SET;
    }
    else
    {
        /* DMA_IT is reset */
        bitstatus = RESET;
    }
    /* Return the DMA_IT status */
    return  bitstatus;
}

/**
  * @brief  Clears the DMA Channelx's interrupt pending bits.
  * @note   Clearing the Global interrupt (DMA_IT_GLx) results in clearing all other
  *         interrupts relative to the same channel (Transfer Complete, Half-transfer
  *         Complete and Transfer Error interrupts: DMA_IT_TCx, DMA_IT_HTx and
  *         DMA_IT_TEx).
  * @param  DMA_IT: specifies the DMA interrupt pending bit to clear.
  *         This parameter can be any combination (for the same DMA) of the following values:
  *          @arg DMA_IT_GL1: DMA Channel1 global interrupt.
  *          @arg DMA_IT_TC1: DMA Channel1 transfer complete interrupt.
  *          @arg DMA_IT_HT1: DMA Channel1 half transfer interrupt.
  *          @arg DMA_IT_TE1: DMA Channel1 transfer error interrupt.
  *          @arg DMA_IT_GL2: DMA Channel2 global interrupt.
  *          @arg DMA_IT_TC2: DMA Channel2 transfer complete interrupt.
  *          @arg DMA_IT_HT2: DMA Channel2 half transfer interrupt.
  *          @arg DMA_IT_TE2: DMA Channel2 transfer error interrupt.
  *          @arg DMA_IT_GL3: DMA Channel3 global interrupt.
  *          @arg DMA_IT_TC3: DMA Channel3 transfer complete interrupt.
  *          @arg DMA_IT_HT3: DMA Channel3 half transfer interrupt.
  *          @arg DMA_IT_TE3: DMA Channel3 transfer error interrupt.
  *          @arg DMA_IT_GL4: DMA Channel4 global interrupt.
  *          @arg DMA_IT_TC4: DMA Channel4 transfer complete interrupt.
  *          @arg DMA_IT_HT4: DMA Channel4 half transfer interrupt.
  *          @arg DMA_IT_TE4: DMA Channel4 transfer error interrupt.
  *          @arg DMA_IT_GL5: DMA Channel5 global interrupt.
  *          @arg DMA_IT_TC5: DMA Channel5 transfer complete interrupt.
  *          @arg DMA_IT_HT5: DMA Channel5 half transfer interrupt.
  *          @arg DMA_IT_TE5: DMA Channel5 transfer error interrupt.
  * @retval None
  */
void DMA_ClearITPendingBit(uint32_t DMA_IT)
{
    DMA_TypeDef *dma_address = NULL;

    uint8_t dma_channel_interrupt = 0;

    /* Check the parameters */
    assert_param(IS_DMA_CLEAR_IT(DMA_IT));

    /*Get the channel interrupt number*/
    dma_channel_interrupt = (uint8_t)((DMA_IT >> 24) & 0x0F);

    /* Calculate the used DMA */
    /* Clear the selected DMA flags */
    dma_address = (DMA_TypeDef *)(DMA_Channel1_BASE + dma_channel_interrupt * 0x00000020);
    dma_address->IFCR |= (DMA_IT & 0x0000000F);

}
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */
